﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using DataMappers;
using System.IO;
using System.Configuration;
using System.Reflection;
using ExaminationTT.Model;
using LoaderLib;
using System.Collections;
using ConcreteMappersAndObjects.DomainObjects;
using ExaminationTT.Rule;
using ExaminationTT.Algorithms;
using OutputGenerator;



namespace ExaminationTT.Control
{
    public class HostApplication
    {
        //data
        private IEntityMapper<int, Student> _studentsMapper;
        private IEntityMapper<int, Semester> _semestersMapper;
        private IEntityMapper<int, CUnit> _cUnitsMapper;
        private IEntityMapper<SubscriptionKey, Subscription> _subscritpionsMapper;
        private IEntityMapper<int, Course> _coursesMapper;
        private IEntityMapper<int, Regime> _regimesMapper;
        private IEntityMapper<int, SClass> _classesMapper;
        private IEntityMapper<int, Teacher> _teachersMapper;
        private IEntityMapper<int, Room> _roomsMapper;
        private IEntityMapper<int, Exam> _examsMapper;
        private IEntityMapper<int, ExamSeason> _examSeasonsMapper;
        private IEntityMapper<RoomExamKey, RoomExam> _roomExamsMapper;
        private List<IExam> _pending;
        private Dictionary<IExam, List<IConflict>> _checked;
        private List<IExam> _unscheduledExams;
        private ILoader _loader;



        //control related

        private List<ExamSeason> _seasons;

        //this field will have all conflits related with exam scheduling
       // private List<IConflict> _conflits;

        //this field will have all Schedulled exams
        //private Dictionary<CUnit, Exam> _exams;

        //this field will have the conflits related with an exam;
        //private Dictionary<Exam, List<IConflict>> _conflitsFromExams;

        //this field will have the students conflits
        //private Dictionary<Student, List<IConflict>> _studentsConflit;


        private List<IRule> _rules;
        private List<ViewRule> _VRules;
        private List<ILoader> _loaders;
        private List<IAlgorithm> _algorithms;
        private HashSet<IConflict> _allConflitList;
        private List<IOutputGenerator> _outputGenerator;

        public HostApplication()
        {
            _seasons = new List<ExamSeason>();
            // É assumido que a UnitOfWork já está inicializada
            _studentsMapper = UnitOfWork.Current.Get<int, Student>(typeof(Student));
            _semestersMapper = UnitOfWork.Current.Get<int, Semester>(typeof(Semester));
            _cUnitsMapper = UnitOfWork.Current.Get<int, CUnit>(typeof(CUnit));
            _subscritpionsMapper = UnitOfWork.Current.Get<SubscriptionKey, Subscription>(typeof(Subscription));
            _coursesMapper = UnitOfWork.Current.Get<int, Course>(typeof(Course));
            _regimesMapper = UnitOfWork.Current.Get<int, Regime>(typeof(Regime));
            _classesMapper = UnitOfWork.Current.Get<int, SClass>(typeof(SClass));
            _teachersMapper = UnitOfWork.Current.Get<int, Teacher>(typeof(Teacher));
            _roomsMapper = UnitOfWork.Current.Get<int, Room>(typeof(Room));
            _examsMapper = UnitOfWork.Current.Get<int, Exam>(typeof(Exam));
            _examSeasonsMapper = UnitOfWork.Current.Get<int, ExamSeason>(typeof(ExamSeason));
            _roomExamsMapper = UnitOfWork.Current.Get<RoomExamKey, RoomExam>(typeof(RoomExam));
            _pending = new List<IExam>();
            _checked = new Dictionary<IExam, List<IConflict>>();
            _unscheduledExams = new List<IExam>();
            _allConflitList = new HashSet<IConflict>();
            _outputGenerator = new List<IOutputGenerator>();
            _VRules = new List<ViewRule>();
            _loader = null;
            RulesUpload();
            LoadersUpload();
            AlgorithmsUpload();
            OutputGeneratorUpload();
            StartUpExams();
        }

        private void StartUpExams()
        {
            List<ExamSeason> lseasson = new List<ExamSeason>();
            _examSeasonsMapper.LoadAllInto(lseasson);
            if (lseasson.Count == 0)
            {
                return;
            }
            List<Exam> lexam = new List<Exam>();
            _examsMapper.LoadAllInto(lexam);
            foreach (var exam in lexam)
            {
                if (exam.Scheduled)
                {
                    SetExam(exam);
                }
                else 
                {
                    _unscheduledExams.Add(exam);
                }
            }
        }

        public IEnumerable<IExamSeason> GetSeasons()
        {
            List<ExamSeason> ret = new List<ExamSeason>();
            _examSeasonsMapper.LoadAllInto(ret);
            return ret;
        }

        public void RunAlgorithm(IAlgorithm a, IEnumerable<DayOfWeek> weekDays, IEnumerable<DateTime> hours)
        {
            //Define dias da semana onde se pode efectuar marcação de exames
            a.SetPossibleWeekDays(weekDays);
            //defina horas possiveis para marcarçao de exames
            a.SetPossibleHours(hours);
            //Unidades curriculares presentes na aplicação
            a.SetCUnits(GetAllCUnits());
            List<IRule> rules = new List<IRule>();
            //selecção de regras activas
            foreach (ViewRule vr in _VRules)
            {
                if (vr.Active) rules.Add(vr.Rule);
            }
            //define as regras activas 
            a.SetRules(rules);
            //define os semestres na aplicação
            a.SetSemesters(MapperControl.GetAllSemesters());
            //define as epocas de exame
            a.SetSeasons(GetSeasons());
            //define os exames já marcados na aplicação, estes não sofrem alterações
            a.SetScheduledExams(GetScheduledExams().Keys);
            //defines exames para efectuar marcação
            a.SetUnScheduledExams(GetUnscheduledExams());
            //execução do algoritmo
            IEnumerable<IExam> examsToSchedule = a.Run();
            //efectua a marcação dos exames marcados pelo algoritmo
            foreach (var exam in examsToSchedule)
            {
                SetExam(exam);
            }
        }
        
        public List<IConflict> GetExamConflits(IExam exam)
        {
            if (_checked.ContainsKey(exam))
            {
                return _checked[exam];
            }
            return null;
        }

        public IEnumerable<IConflict> GetAllConflits()
        {
            return _allConflitList;
        }

        public Dictionary<IExam, List<IConflict>> GetScheduledExams()
        {
            return _checked;// _checked.Count == 0 ? _start : _checked;
        }

        public IEnumerable<IExam> ExportScheduledExams()
       {
           return _checked.Keys;
       }

        public IEnumerable<IExam> GetUnscheduledExams()
        {
            List<ExamSeason> lseason = new List<ExamSeason>();
            _examSeasonsMapper.LoadAllInto(lseason);
            List<IExam> lexam = new List<IExam>();
            List<CUnit> lu = new List<CUnit>();
            _cUnitsMapper.LoadAllInto(lu);
            //if(_unscheduledExams.Count != 0)
            //{
            //    foreach (var unscheduledExam in _unscheduledExams)
            //    {
            //        lu.RemoveAll((lu.Where(cu => (cu.ID == unscheduledExam.CUnit.ID)).Contains));
            //    }
            //}
            foreach (var examSeason in lseason)
            {
                foreach (var cunit in lu)
                {
                    IExam e = GetUnscheduledExam(cunit, examSeason);
                    if (e != null)
                    {
                        lexam.Add(e);
                    }
                }
            }
         //   lexam.AddRange(_unscheduledExams);
            return lexam;
        }



        public IExam GetUnscheduledExam(ICUnit UC, IExamSeason season)
        {
            if (UC is CUnit && season is ExamSeason)
            {
                //valida se as instancias passadas por parametro sao efectivamente as instancias com que a host passou 
                if (_cUnitsMapper.GetByID(((CUnit)UC).ID) != UC
                    || _examSeasonsMapper.GetByID(((ExamSeason)season).ID) != season)
                {
                    return null;
                }
            }
            else {
                return null;
            }
            foreach (var exam in _checked.Keys)
            {
                if (exam.CUnit == UC && exam.Season == season) return null;
            }
            foreach (Exam exam in _unscheduledExams)
            {
                if (exam.CUnit == UC && exam.Season == season) return exam;
            }
            Exam newExam = new Exam{CUnit = (CUnit)UC , Season = (ExamSeason)season, ExamDate = season.StartSeason , ExamEndDate = season.StartSeason.AddHours(3)};
            _unscheduledExams.Add(newExam);
            return newExam;
        }

        /*public void SetScheduleExame(Dictionary<IExam, List<IConflit>> schedule)
        {
            _checked = schedule;
        }*/

        private IExam examInProcess = null;

        private void ClearExamConflits(IExam exam)
        {
            if (exam != null && _checked.ContainsKey(exam))
            {
         
                _allConflitList.RemoveWhere(conf => conf.Exams.Contains(exam));
                _checked[exam].Clear();
                foreach (var item in _checked.Values)
                {
                    item.RemoveAll(conf => conf.Exams.Contains(exam));
                }
            }
        }

        public List<IConflict> SetExam(IExam exam)
        {

            examInProcess = exam;
            if (_checked.Count == 0)
            {
                _unscheduledExams.Remove(exam);
                exam.Scheduled = true;
                _checked.Add(exam, new List<IConflict>());
                return _checked[exam];
            }
            List<IConflict> conflit = new List<IConflict>();
            HashSet<Exam> conflitedexams = new HashSet<Exam>();
            foreach (Exam checkedExam in _checked.Keys)
            {
                if(checkedExam == exam) continue;
                foreach (ViewRule rule in _VRules.Where(rule => rule.Active))
                {
                    IConflict tmp = rule.Rule.EnforceRule(exam, checkedExam);
                    if (tmp != null)
                    {
                        conflit.Add(tmp);
                        conflitedexams.Add(checkedExam);
                    }
                }
            }
            if (!_checked.ContainsKey(exam))
            {
                _checked.Add(exam, new List<IConflict>());
            }
            else
            {
                ClearExamConflits(exam);
            }
            
            if (conflit.Count != 0)
            {
                _checked[exam].AddRange(conflit);
                foreach (Exam e in conflitedexams)
                {
                    _checked[e].AddRange(conflit.Where(conf => conf.Exams.Contains(e)));
                }
                foreach (var item in conflit)
                {
                    _allConflitList.Add(item);
                }
                
            }
            _unscheduledExams.Remove(exam);
            examInProcess = null;
            exam.Scheduled = true;
            return _checked[exam];
        }
        /// <summary>
        /// Remove exam.
        /// </summary>
        /// <param name="exam"></param>
        /// <returns>Null if exam is processing else List of conflits of the exam</returns>
        public List<IConflict> RemoveExam(IExam exam)
        {
            if (exam == examInProcess && _checked.Count > 1) return null;
            List<IConflict> toReturn = new List<IConflict>();
            toReturn.AddRange(_checked[exam]);
            _checked.Remove(exam);
            _unscheduledExams.Add(exam);
            foreach (var innerExam in _checked.Keys)
            {
                //Criar lista temp para depois remover 
                List<IConflict> conflitsToRemove = new List<IConflict>();
                //ve os conflitos
                foreach (var conflit in _checked[innerExam])
                {
                    //se o conflito tiver o exame adicionar esse exame
                    if (conflit.Exams.Contains(exam))
                    {
                        conflitsToRemove.Add(conflit);
                        _allConflitList.Remove(conflit);
                    }
                }
                toReturn.AddRange(conflitsToRemove);
                //remove todos os conflitos que adicionados anteriormente
                _checked[innerExam].RemoveAll(conflitsToRemove.Contains);
            }
            exam.Scheduled = false;
            return toReturn;
        }

        public void Setup()
        {
            UnitOfWork.Current.DeleteAllObjects();
            //Room - simple
            List<Room> rooms = new List<Room>();
            //ISemester - simple
            List<Semester> semesters = new List<Semester>();
            //Regime - simple
            List<Regime> regimes = new List<Regime>();
            //Course - simple
            List<Course> courses = new List<Course>();
            //teachers - simple
            List<Teacher> teachers = new List<Teacher>();
            //CUnit - Semesters, Teacher, course
            //array com {Semesters, Teacher, Course}
            Dictionary<CUnit, IEnumerable<String>[]> cunits = new Dictionary<CUnit, IEnumerable<string>[]>();
            //Class - Regime, Course, Semester
            //array com {Regime, Course} Semester não é necessário
            Dictionary<SClass, string[]> classes = new Dictionary<SClass, string[]>();
            //Students - Subscriptions
            //Lista de subscriptions
            Dictionary<Student, IEnumerable<string>> students = new Dictionary<Student, IEnumerable<string>>();



            if (_loader != null)
            {
                IEnumerable<IExternalDataTypes.IStudent> externalStudents = _loader.GetStudents();
                IEnumerable<IExternalDataTypes.ICourse> externalCourses = _loader.GetCourse();
                IEnumerable<IExternalDataTypes.ISemester> externalSemesters = _loader.GetSemester();
                IEnumerable<IExternalDataTypes.ICUnit> externalCUnits = _loader.GetCUnit();
                IEnumerable<IExternalDataTypes.IRegime> externalRegimes = _loader.GetRegime();
                IEnumerable<IExternalDataTypes.IRoom> externalRooms = _loader.GetRoom();
                IEnumerable<IExternalDataTypes.ITeacher> externalTeachers = _loader.GetTeacher();
                IEnumerable<IExternalDataTypes.IClass> externalClasses = _loader.GetClass();

                foreach (IExternalDataTypes.ITeacher teacher in externalTeachers)
                {
                    Teacher t = new Teacher();
                    ExternalToInternalObjects.TeacherParse(teacher, t);
                    teachers.Add(t);
                }
                int subCount = 0;
                foreach (IExternalDataTypes.IStudent student in externalStudents)
                {
                    Student s = new Student();
                    ExternalToInternalObjects.StudentParse(student, s);
                    students.Add(s, student.Subscriptions);
                    subCount += student.Subscriptions.Count();
                    //regime nao é necessário
                }
                foreach (IExternalDataTypes.ICourse course in externalCourses)
                {
                    Course c = new Course();
                    ExternalToInternalObjects.CourseParser(course, c);
                    courses.Add(c);
                }
                foreach (IExternalDataTypes.ISemester semester in externalSemesters)
                {
                    Semester s = new Semester();
                    ExternalToInternalObjects.SemesterParser(semester, s);
                    semesters.Add(s);
                }
                foreach (IExternalDataTypes.ICUnit cunit in externalCUnits)
                {
                    CUnit c = new CUnit();
                    ExternalToInternalObjects.CUnitParser(cunit, c); //semesters teacher course
                    IEnumerable<string>[] arrCUnit = { cunit.Semesters, cunit.Teacher, cunit.Course };
                    cunits.Add(c, arrCUnit);
                }
                foreach (IExternalDataTypes.IRegime regime in externalRegimes)
                {
                    Regime r = new Regime();
                    ExternalToInternalObjects.RegimeParser(regime, r);
                    regimes.Add(r);
                }
                foreach (IExternalDataTypes.IRoom room in externalRooms)
                {
                    Room r = new Room();
                    ExternalToInternalObjects.RoomParser(room, r);
                    rooms.Add(r);
                }
                //foreach (IClass sclass in externalClasses)
                //{   
                //    SClass sc = new SClass();
                //    ExternalToInternalObjects.ClassParser(sclass, sc);//{Regime, Course}
                //    string[] arrSClass = {sclass.Regime, sclass.Courses};
                //    classes.Add(sc, arrSClass);
                //}
                UnitOfWork.Current.Save();

                List<Subscription> subscriptionsToSave = new List<Subscription>();
                List<CUSemester> cusSemToSave = new List<CUSemester>();
                List<TeacherClassCUnit> tccuToSave = new List<TeacherClassCUnit>();

                //agora vamos construir as ligações
                //cunits, classes, students
                //Students - adicionar subscriptions
                //foreach (Student student in students.Keys)
                //{
                //    List<CUnit> subscriptions = new List<CUnit>();
                //    InFilter filter = new InFilter(students[student], "Acronym");
                //    _cUnitsMapper.LoadFilteredInto(subscriptions, filter);
                //    foreach (CUnit cunit in subscriptions)
                //    {
                //        Subscription sub = new Subscription();
                //        sub.CUnit = cunit;
                //        sub.Student = student;
                //        subscriptionsToSave.Add(sub);
                //    }
                //}

                
                foreach (Student student in students.Keys)
                {
                    List<CUnit> subscriptions = new List<CUnit>();
                    InFilter filter = new InFilter(students[student], "Acronym"); // where acronym in 
                    _cUnitsMapper.LoadFilteredInto(subscriptions, filter);

                    foreach (CUnit cunit in subscriptions)
                    {
                        Subscription sub = new Subscription();
                        sub.CUnit = cunit;
                        sub.Student = student;
                        subscriptionsToSave.Add(sub);
                    }
                }

                //classes - adicionar Regime e Course
                foreach (IExternalDataTypes.IClass sclass in externalClasses)
                {
                    SClass cls = new SClass();
                    ExternalToInternalObjects.ClassParser(sclass, cls);
                    List<Regime> regs = new List<Regime>();
                    InFilter regFilter = new InFilter(new String[] { sclass.Regime }, "Description");
                    _regimesMapper.LoadFilteredInto(regs, regFilter);
                    //TODO - create our Exceptions
                    if (regs.Count != 1) { throw new Exception("Invalid readed data"); }
                    cls.Regime = regs[0];
                    List<Course> crs = new List<Course>();
                    InFilter crsFilter = new InFilter(new String[] { sclass.Courses }, "Acronym");
                    _coursesMapper.LoadFilteredInto(crs, crsFilter);
                    if (crs.Count != 1) { throw new Exception("Invalid readed data"); }
                    cls.Course = crs[0];
                    classes.Add(cls, null);
                }
                //cunits - adicionar semester, teacher, course
                foreach (CUnit cunit in cunits.Keys)
                {
                    List<Semester> sems = new List<Semester>();
                    InFilter semFilter = new InFilter(cunits[cunit][0], "Description");
                    _semestersMapper.LoadFilteredInto(sems, semFilter);
                    foreach (Semester s in sems)
                    {
                        CUSemester cus = new CUSemester();
                        cus.CUnit = cunit;
                        cus.Semester = s;
                        cusSemToSave.Add(cus);
                    }
                    List<SClass> scls = new List<SClass>();
                    InFilter sclsFilter = new InFilter(cunits[cunit][0], "Name");
                    _classesMapper.LoadFilteredInto(scls, sclsFilter);
                    foreach (var item in scls)
                    {
                        TeacherClassCUnit tccu = new TeacherClassCUnit();
                        tccu.CUnit = cunit;
                        tccu.Class = item;
                        //falta teacher
                        tccuToSave.Add(tccu);
                    }

                }
                UnitOfWork.Current.Save();
                // UnitOfWork.Current.Refresh();

            }
        }

        public void ActivateRule(IRule rule)
        {
            foreach (var vr in _VRules)
            {
                if (vr.Rule == rule) { vr.Active = true; return; }
            }
        }

        public void DeactivateRule(IRule rule)
        {
            foreach (var vr in _VRules)
            {
                if (vr.Rule == rule) { vr.Active = false; return; }
            }
        }

        public void SetLoader(ILoader loader)
        {
            _loader = loader;
        }

        private void RulesUpload()
        {
            string p = System.Reflection.Assembly.GetAssembly(this.GetType()).Location;


            string rulesPath = ConfigurationManager.AppSettings["RulesPath"];
            string[] filesInPath = Directory.GetFiles(rulesPath);
            List<IRule> rules = new List<IRule>();
            foreach (var file in filesInPath)
            {
                FileInfo f = new FileInfo(file);
                if (f.Extension.Equals(".dll"))
                {
                    Assembly a = Assembly.LoadFrom(f.FullName);
                    Type[] ta = a.GetExportedTypes();
                    foreach (var type in ta)
                    {
                        if (typeof(IRule).IsAssignableFrom(type))
                        {
                            rules.Add((IRule)Activator.CreateInstance(type));
                        }
                    }
                }
            }
            _rules = rules;
            foreach (var rule in rules)
            {
                _VRules.Add(new ViewRule(rule));
            }
        }

        private void LoadersUpload()
        {

            string loadersPath = ConfigurationManager.AppSettings["LoadersPath"];
            string[] filesInPath = Directory.GetFiles(loadersPath);
            List<ILoader> loaders = new List<ILoader>();
            foreach (var s in filesInPath)
            {
                FileInfo f = new FileInfo(s);
                if (f.Extension.Equals(".dll"))
                {
                    Assembly a = Assembly.LoadFrom(f.FullName);
                    Type[] ta = a.GetExportedTypes();
                    foreach (var type in ta)
                    {
                        if (typeof(ILoader).IsAssignableFrom(type))
                        {
                            loaders.Add((ILoader)Activator.CreateInstance(type));
                            //_toolItems[0] = new ToolStripButton(_l.Getname(), null, (sender, e) => GetData());
                        }
                    }
                }
            }
            _loaders = loaders;
        }

        private void AlgorithmsUpload()
        {
            string algorithmsPath = ConfigurationManager.AppSettings["AlgorithmsPath"];
            string[] filesInPath = Directory.GetFiles(algorithmsPath);
            List<IAlgorithm> algorithms = new List<IAlgorithm>();
            foreach (var s in filesInPath)
            {
                FileInfo f = new FileInfo(s);
                if (f.Extension.Equals(".dll"))
                {
                    Assembly a = Assembly.LoadFrom(f.FullName);
                    Type[] ta = a.GetExportedTypes();
                    foreach (var type in ta)
                    {
                        if (typeof(IAlgorithm).IsAssignableFrom(type))
                        {
                            algorithms.Add((IAlgorithm)Activator.CreateInstance(type));
                        }
                    }
                }
            }
            _algorithms = algorithms;
        }

        private void OutputGeneratorUpload()
        {

            string loadersPath = ConfigurationManager.AppSettings["OutputGeneratorPath"];
            string[] filesInPath = Directory.GetFiles(loadersPath);
            List<IOutputGenerator> loaders = new List<IOutputGenerator>();
            foreach (var s in filesInPath)
            {
                FileInfo f = new FileInfo(s);
                if (f.Extension.Equals(".dll"))
                {
                    Assembly a = Assembly.LoadFrom(f.FullName);
                    Type[] ta = a.GetExportedTypes();
                    foreach (var type in ta)
                    {
                        if (typeof(IOutputGenerator).IsAssignableFrom(type))
                        {
                            loaders.Add((IOutputGenerator)Activator.CreateInstance(type));
                            //_toolItems[0] = new ToolStripButton(_l.Getname(), null, (sender, e) => GetData());
                        }
                    }
                }
            }
            _outputGenerator = loaders;
        }

        /// <summary>
        /// This template method will setup an algorithm and run it. It may throw InvalidOperationException if the data it's not set up properly. Check data after this method is finished
        /// </summary>
        /// <param name="alg">algorithm that will run</param>
        /// <param name="hours">defined hours for algorithm exams</param>
        /// <param name="weekDays">possible week days to schedule an exam</param>
        public void Run(IAlgorithm alg, IEnumerable<DateTime> hours, IEnumerable<DayOfWeek> weekDays)
        {
            //alg.SetCUnits(cunits);
            //alg.SetRules(rules);
            //alg.SetSemesters(semesters);
            //alg.SetPossibleHours(hours);
            //alg.SetPossibleWeekDays(wd);
            //alg.SetScheduledExams(scheduledExams);
            //alg.SetUnScheduledExams(unscheduledExams);
            //alg.Run();
        }

        public List<IRule> GetRules()
        {
            return _rules.ToList();
        }

        public List<ILoader> GetLoaders()
        {
            return _loaders.ToList();
        }

        public List<IAlgorithm> GetAlgorithms()
        {
            return _algorithms.ToList();
        }

        public List<IOutputGenerator> GetOutputGenerator()
        {
            return _outputGenerator.ToList();
        }

        public IEnumerable<ICUnit> GetAllCUnits()
        {
            List<CUnit> cunits = new List<CUnit>();
            _cUnitsMapper.LoadAllInto(cunits);
            return cunits;
        }

        public IEnumerable<IExamSeason> GetExamSeasons()
        {
            List<ExamSeason> seasons = new List<ExamSeason>();
            _examSeasonsMapper.LoadAllInto(seasons);
            return seasons;
        }

        public IEnumerable<IRoom> GetAllRooms()
        {
            List<Room> rooms = new List<Room>();
            _roomsMapper.LoadAllInto(rooms);
            return rooms;
        }

        public IEnumerable<IRoomExam> GetAllReservedRooms()
        {
            List<RoomExam> res = new List<RoomExam>();
            _roomExamsMapper.LoadAllInto(res);
            return res;
        }

        public bool SetExamRoom(IExam exam, IRoom room)
        {
            if (exam is Exam && room is Room)
            { 
                if(_roomsMapper.GetByID(((Room)room).ID) == room)
                {
                    return ((Exam)exam).AddRoom((Room)room);
                }
            }
            return false;
        }

        public bool RemoveExamRoom(IExam exam, IRoom room)
        {
            if (exam is Exam && room is Room)
            {
                return ((Exam)exam).RemoveRoom((Room)room);
            }
            return false;
        }

        public void SaveAllState()
        {
            UnitOfWork.Current.Save();
        }
    }

}
